package com.urbane.generator.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.api.R;
import com.urbane.generator.entity.DataSources;
import com.urbane.generator.model.vo.ResponseResult;
import com.urbane.generator.service.DataSourceService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * 数据库元数据控制器
 * <p>提供前端界面动态获取数据库表结构和字段信息的 API 接口</p>
 * <p>这是实现“可视化代码生成”的核心，前端依赖此接口来展示可选的表和字段</p>
 *
 * @author your-name
 * @date 2024-07-07
 */
@RestController
@RequestMapping("/api/db-meta")
@Tag(name = "系统管理", description = "代码生成平台的系统管理接口")
public class DatabaseMetaController {

    @Autowired
    private DataSourceService dataSourceService;

    /**
     * 获取指定数据源下的所有数据库表名及注释
     *
     * <p>此接口是前端“表选择器”组件的数据源。用户选择一个数据源后，前端调用此接口获取所有表。</p>
     * <p>返回格式：[{"name":"t_user","comment":"用户表"},{"name":"t_product","comment":"商品表"}]</p>
     *
     * @param dataSourceId 数据源ID（必须）
     * @return 表名和注释的列表
     * @api {GET} /api/db-meta/tables 获取数据库表列表
     * @apiName GetTablesByDataSource
     * @apiGroup 系统管理
     * @apiParam {Number} dataSourceId 数据源ID（必须）
     * @apiSuccessExample {json} 成功响应:
     *     HTTP/1.1 200 OK
     *     {
     *       "code": 200,
     *       "msg": "success",
     *       "data": [
     *         {
     *           "name": "t_user",
     *           "comment": "用户表"
     *         },
     *         {
     *           "name": "t_product",
     *           "comment": "商品表"
     *         }
     *       ]
     *     }
     * @apiErrorExample {json} 数据源不存在:
     *     HTTP/1.1 404 Not Found
     *     {
     *       "code": 404,
     *       "msg": "数据源不存在",
     *       "data": null
     *     }
     * @apiErrorExample {json} 连接失败:
     *     HTTP/1.1 500 Internal Server Error
     *     {
     *       "code": 500,
     *       "msg": "连接数据库失败：Access denied for user 'xxx'@'localhost'",
     *       "data": null
     *     }
     */
    @GetMapping("/tables")
    @Operation(summary = "根据数据源获取数据库表列表", description = "查询指定数据源下所有表的名称和注释，用于前端表选择器")
    public ResponseResult<List<TableInfo>> getTablesByDataSource(@Parameter(description = "数据源ID，必须存在", required = true) @RequestParam Long dataSourceId) {
        // 1. 通过数据源ID获取配置
        DataSources source = dataSourceService.getDataSourcesMapper().selectById(dataSourceId);
        if (source == null) {
            return ResponseResult.fail(404, "数据源不存在");
        }

        // 2. 调用服务层，通过 JDBC 元数据查询表信息
        // 注意：这里我们使用了 DataSourceService 中的 getTablesByDataSource 方法
        // 它内部使用了标准的 JDBC DatabaseMetaData 来查询，不依赖 MyBatis-Plus 的生成器
        List<TableInfo> tables = dataSourceService.getTablesByDataSource(source);

        return ResponseResult.success(tables);
    }

    /**
     * 获取指定表的所有字段信息
     *
     * <p>此接口是前端“字段查看器”的数据源。用户在表选择器中选中一个表后，前端调用此接口获取该表的所有字段详情。</p>
     * <p>返回字段信息包括：字段名、注释、类型、是否为主键、是否为自增、是否为逻辑删除、是否为乐观锁等。</p>
     *
     * @param dataSourceId 数据源ID
     * @param tableName 表名（如：t_user）
     * @return 字段信息列表
     * @api {GET} /api/db-meta/fields 获取数据库表字段列表
     * @apiName GetFieldsByTable
     * @apiGroup 系统管理
     * @apiParam {Number} dataSourceId 数据源ID（必须）
     * @apiParam {String} tableName 表名（必须）
     * @apiParamExample {url} 请求示例:
     *     /api/db-meta/fields?dataSourceId=1&tableName=t_user
     * @apiSuccessExample {json} 成功响应:
     *     HTTP/1.1 200 OK
     *     {
     *       "code": 200,
     *       "msg": "success",
     *       "data": [
     *         {
     *           "name": "id",
     *           "comment": "主键ID",
     *           "type": "BIGINT",
     *           "keyFlag": true,
     *           "autoIncrement": true,
     *           "logicDelete": false,
     *           "version": false
     *         },
     *         {
     *           "name": "username",
     *           "comment": "用户名",
     *           "type": "VARCHAR",
     *           "keyFlag": false,
     *           "autoIncrement": false,
     *           "logicDelete": false,
     *           "version": false
     *         },
     *         {
     *           "name": "create_time",
     *           "comment": "创建时间",
     *           "type": "DATETIME",
     *           "keyFlag": false,
     *           "autoIncrement": false,
     *           "logicDelete": false,
     *           "version": false
     *         }
     *       ]
     *     }
     */
    @GetMapping("/fields")
    @Operation(summary = "根据数据源和表名获取字段信息", description = "查询指定表的所有字段的详细信息，用于前端展示和字段映射")
    public ResponseResult<List<FieldInfo>> getFieldsByTable(
            @Parameter(description = "数据源ID", required = true) @RequestParam Long dataSourceId,
            @Parameter(description = "表名，如：t_user", required = true) @RequestParam String tableName) {

        // 1. 验证数据源
        DataSources source = dataSourceService.getDataSourcesMapper().selectById(dataSourceId);
        if (source == null) {
            return ResponseResult.fail(404, "数据源不存在");
        }

        // 2. 调用服务层获取字段信息
        List<FieldInfo> fields = dataSourceService.getFieldsByTableName(source, tableName);

        return ResponseResult.success(fields);
    }

    // ==================== 内部类：数据结构定义 ====================

    /**
     * 数据库表信息（用于返回给前端）
     */
    public static class TableInfo {
        private String name;     // 表名，如：t_user
        private String comment;  // 表注释，如：用户表

        public TableInfo(String name, String comment) {
            this.name = name;
            this.comment = comment;
        }

        // Getter & Setter
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
        public String getComment() { return comment; }
        public void setComment(String comment) { this.comment = comment; }
    }

    /**
     * 数据库字段信息（用于返回给前端）
     */
    public static class FieldInfo {
        private String name;              // 字段名，如：id
        private String comment;           // 字段注释，如：主键ID
        private String type;              // 字段类型，如：VARCHAR、BIGINT、DATETIME
        private Boolean keyFlag;          // 是否为主键
        private Boolean autoIncrement;    // 是否为自增
        private Boolean logicDelete;      // 是否为逻辑删除字段（数据库字段名匹配）
        private Boolean version;          // 是否为乐观锁字段（数据库字段名匹配）
        private Boolean fill;             // 是否为自动填充字段（如 create_time, update_time）

        public FieldInfo(String name, String comment, String type, Boolean keyFlag, Boolean autoIncrement,
                         Boolean logicDelete, Boolean version, Boolean fill) {
            this.name = name;
            this.comment = comment;
            this.type = type;
            this.keyFlag = keyFlag;
            this.autoIncrement = autoIncrement;
            this.logicDelete = logicDelete;
            this.version = version;
            this.fill = fill;
        }

        // Getter & Setter
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }

        public String getComment() { return comment; }
        public void setComment(String comment) { this.comment = comment; }

        public String getType() { return type; }
        public void setType(String type) { this.type = type; }

        public Boolean getKeyFlag() { return keyFlag; }
        public void setKeyFlag(Boolean keyFlag) { this.keyFlag = keyFlag; }

        public Boolean getAutoIncrement() { return autoIncrement; }
        public void setAutoIncrement(Boolean autoIncrement) { this.autoIncrement = autoIncrement; }

        public Boolean getLogicDelete() { return logicDelete; }
        public void setLogicDelete(Boolean logicDelete) { this.logicDelete = logicDelete; }

        public Boolean getVersion() { return version; }
        public void setVersion(Boolean version) { this.version = version; }

        public Boolean getFill() { return fill; }
        public void setFill(Boolean fill) { this.fill = fill; }
    }
}